package com.example.aiagent.controller;

import cn.hutool.core.io.FileUtil;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.exception.UploadFileException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.aiagent.annotation.AuthCheck;
import com.example.aiagent.app.LoveApp;
import com.example.aiagent.common.BaseResponse;
import com.example.aiagent.common.ResultUtils;
import com.example.aiagent.constant.FileConstant;
import com.example.aiagent.constant.UserConstant;
import com.example.aiagent.demo.invoke.VisionInvoke;
import com.example.aiagent.exception.BusinessException;
import com.example.aiagent.exception.ErrorCode;
import com.example.aiagent.exception.ThrowUtils;
import com.example.aiagent.manager.CosManager;
import com.example.aiagent.model.dto.chathistory.ChatHistoryQueryRequest;
import com.example.aiagent.model.entity.ChatHistory;
import com.example.aiagent.model.entity.User;
import com.example.aiagent.service.AppService;
import com.example.aiagent.service.ChatHistoryService;
import com.example.aiagent.service.UserService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;

@Slf4j
@RestController
@RequestMapping("/ai")
@Tag(name = "AI", description = "AI相关接口")
public class AIController {

//    @Resource
//    private LoveApp loveApp;
    @Resource
    private UserService userService;
    @Resource
    private ChatHistoryService chatHistoryService;
    @Resource
    private AppService appService;
    @Autowired
    private LoveApp loveApp;
    @Resource
    private CosManager cosManager;

    /**
     *
     * 同步对话接口
     * @param message
     * @param chatId
     * @param request
     * @return
     */
    @GetMapping("/chat/sync")
    @Operation(description = "完整输出全部内容后再传到前端",summary = "同步对话接口")
    public BaseResponse<String> doChatWithSync(String message, Long chatId, HttpServletRequest request,Long aiId) {
        User loginUser = userService.getLoginUser(request);
        return ResultUtils.success(appService.doChatSync(message, chatId, loginUser,aiId));
    }

//    @GetMapping(value = "/chat/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
//    public BaseResponse<Flux<String>> doChatWithSSE(String message,
//                                                    Long appId,
//                                                    HttpServletRequest request) {
////        User loginUser = userService.getLoginUser(request);
////        return ResultUtils.success(appService.doChatWithStream(message, appId, loginUser));
//        return ResultUtils.success(loveApp.doChatWithStream(message, appId));
//    }

    /**
     * 流式输出效果
     * @param message
     * @param chatId
     * @param request
     * @return
     */
    @Operation(summary = "流式对话接口", description = "实时输出内容到前端，可以形成打字机效果")
    @GetMapping(value = "/chat/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> doChatWithAppSSE(String message, Long chatId,Long aiId , HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        return appService.doChatWithStream(message, chatId, loginUser, aiId);
    }

    @Operation(summary = "文本转语音接口", description = "专门给dify平台提供的")
    @GetMapping("/chat/audio")
    public String textToAudio(String message, Long chatId,Long aiId) {
        return appService.dotextToAudio(message, chatId, aiId);
    }



    /**
     * 分页查询某个应用的对话历史（游标查询）
     *
     * @param appId          应用ID
     * @param pageSize       页面大小
     * @param lastCreateTime 最后一条记录的创建时间
     * @param request        请求
     * @return 对话历史分页
     */
    @GetMapping("/app/{appId}")
    @Operation(description = "查询AI和用户的对话，每次十条", summary = "列出对话记录")
    public BaseResponse<Page<ChatHistory>> listAppChatHistory(@PathVariable Long appId,
                                                              @RequestParam(defaultValue = "10") int pageSize,
                                                              @RequestParam(required = false) LocalDateTime lastCreateTime,
                                                              HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        Page<ChatHistory> result = chatHistoryService.listAppChatHistoryByPage(appId, pageSize, lastCreateTime, loginUser);
        return ResultUtils.success(result);
    }

    /**
     * 删除相关编号的对话
     * @param appId
     * @return
     */
    @PostMapping("/app/deleteApp")
    @Operation(summary = "删除会话")
    public BaseResponse<Integer> deleteApp(Long appId, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        return ResultUtils.success(appService.deleteApp(appId, loginUser));
    }

    /**
     * 解析各种类型文档
     * @param file
     * @param message
     * @param chatId
     * @param request
     * @return
     * @throws IOException
     */
    @PostMapping("/upload/doc")
    @Operation(summary= "上传办公文件")
    public Flux<String> uploadFile(@RequestParam("file")MultipartFile file,
                                   String message,
                                   Long chatId,
                                   HttpServletRequest request) throws IOException {
        User loginUser = userService.getLoginUser(request);
        // 保存文件到本地文件夹
        // 1. 校验文件是否为空
        ThrowUtils.throwIf(file.isEmpty(), ErrorCode.PARAMS_ERROR);
        // 2. 构造文件存放地址
        String FILE_DIR = FileConstant.FILE_SAVE_DIR + "/file";
        String fileName = file.getOriginalFilename();
        String filePath = FILE_DIR + "/" + fileName;
        // 3.保存文件操作
        FileUtil.writeBytes(file.getBytes(), filePath);
        // 4.调用AI生成结果
        return appService.doChatWithDoc(message, chatId, loginUser, fileName);
    }

    @PostMapping("upload/img")
    @Operation(summary = "上传图片")
    public Flux<String> uploadImg(@RequestPart("img") MultipartFile multipartFile,
                                  HttpServletRequest request,
                                  String message,
                                  Long chatId) throws IOException, NoApiKeyException, UploadFileException {
        User loginUser = userService.getLoginUser(request);
        // 上传图片到云端
        //文件目录
        String filename = multipartFile.getOriginalFilename();
        String filepath = String.format("/test/%s", filename);
        //转换文件类型
        File file = null;
        try {
            file = File.createTempFile(filepath, null);
            multipartFile.transferTo(file);
            //上传文件
            cosManager.putObject(filepath, file);
        } catch (Exception e) {
            log.error("file upload error, filepath = " + filepath, e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传失败");
        } finally {
            //删除临时文件
            if (file != null) {
                boolean delete = file.delete();
                if (!delete) {
                    log.error("file delete error, filepath = {}", filepath);
                }
            }
        }
        // 构造文件链接
        String url = "https://picture-1332806968.cos.ap-shanghai.myqcloud.com/test/" + filename;
        // 调用AI识别图片
        return appService.doChatWithImg(message, chatId, loginUser, url);
    }


}
